define(function (require, exports, module) {
	var Picker = module.exports = function(config, view){
		this.initailize(config, view);
		return this;
	};
	
	Picker.prototype = {
		/**
		 * 初始化方法
		 */
		initailize:function(config, view){
			this._config = $.extend({}, this._defaultConfig);
			if(config){
				this._config = $.extend(this._config, config);
			}
			
			// 由于目前采取单页模式,创建时必须输入view参数
			if(!view){
				alert("picker:请输入view参数");
				return;
			}
			
			this._doc = view ? view.$el : document.body;
			
			// 用于测试样式的对象
			this._mod = document.createElement('modernizr').style;
			
			this._prefix = this._testPrefix();
			
			this._createDialog();
			
			this._buildButtons();
			
			this._buildColumns();
			
		},
		
		/**
		 * 默认设置
		 */
		_defaultConfig:{
			fixTime:100,
			scrollTime:300,
			scrollOffset:2,
			onShow:null,
			onHide:null,
			onItemSelect:null
		},
		/**
		 * 点击事件
		 */
		_tap_event:"tap",
		
		/**
		 * 
		 */
		_begin_event:("ontouchstart" in document) ? "touchstart" : "mousedown",
				
		_move_event:("ontouchmove" in document) ? "touchmove" : "mousemove",
				
		_end_event:("ontouchend" in document) ? "touchend" : "mouseup",
		
		/**
		 * 作用域
		 */
		_doc:null,
		
		_endYear:null,
		
		_dialog:null,
		
		_buttonArea:null,
		
		_titleArea:null,
		
		_scrollerArea:null,

		_uls:null,
		
		_titles:null,
		
		_config:null,

		_testPrefix:function(){
			var prefixes = ['webkit', 'Moz', 'O', 'ms'];
			for(p in prefixes){
				if(this._mod[prefixes[p] + "Transform"] !== undefined){
					return prefixes[p];
				}
			}
		},

		_createDialog:function(){
			var dialogHtml = [
				"<div class='nu-picker z1400' style=''>",
					"<div class='nu-picker-block'></div>",
					"<div class='nu-picker-container'>",
						"<div class='nu-picker-button-area'></div>",
						"<div class='nu-picker-title-area'></div>",
						"<div class='nu-picker-scroller-area'></div>",
					"</div>",
				"</div>"
			].join("");

			this._dialog = $(dialogHtml);
			
			this._buttonArea = this._dialog.find(".nu-picker-button-area");
			
			this._titleArea = this._dialog.find(".nu-picker-title-area");
			
			this._scrollerArea = this._dialog.find(".nu-picker-scroller-area");
			
			this._dialog.find(".nu-picker-block").bind(this._tap_event, $.proxy(function(){
				this.hide();
			}, this));
			
			this._dialog.hide().appendTo(this._doc);
			
		},
		
		_buildButtons:function(){
			
			$("<button class='FR'>确定</button>")
				.appendTo(this._buttonArea)
				.on(this._tap_event, $.proxy(function(){
					this.hide(this.getOutput());
					return false;
				}, this));
			
			$("<button>取消</button>")
				.appendTo(this._buttonArea)
				.on(this._tap_event, $.proxy(function(){
					this.hide();
					return false;
				}, this));
				
			if(this._config.buttons){
				for(var i = 0; i < this._config.buttons.length; i++){
					var content = this._config.buttons[i].content;
					var func = this._config.buttons[i].func;
					
					$(content)
					.appendTo(this._buttonArea)
					.on(this._tap_event, $.proxy(func, this));
				}
			}
			
		},
		
		_buildColumns:function(){
			this._titles = [];
			this._uls = [];
			
			for(var i = 0; i < this._config.scrollers.length; i++){
				var scrollerConfig = this._config.scrollers[i];
				
				// add title
				this._titles[i] = $("<div class='nu-picker-title' style='flex:" + scrollerConfig.flex + ";'>" + scrollerConfig.title + "</div>");
				this._titleArea.append(this._titles[i]);
				
				// add scroller
				this._uls[i] = this._buildScroller(scrollerConfig, i);
				
			}
		},
		
		_buildLis:function(ul, data){
			var content = "";
			for(var i = 0; i < data.length; i++){
				content += "<li class='nu-picker-valid' value='" + data[i].key + "'>" + data[i].text + "</li>";
			}
			ul.empty();
			$(content).appendTo(ul);
		},
		
		_buildScroller:function(scrollerConfig, ulIndex){
			var scrollerHtml = [
				"<div class='nu-picker-scroller' style='flex:" + scrollerConfig.flex + ";'>",
					"<ul></ul>",
					"<div class='nu-picker-scroller-mark'></div>",
				"</div>",
			].join("");
			
			var scroller = $(scrollerHtml).appendTo(this._scrollerArea);
			var ul = scroller.find("ul");
			
			this._buildLis(ul, scrollerConfig.data);
			
			// init
			ul.children().eq(0).addClass("nu-picker-select");
			
			var picker = this;
			var timeout;
			scroller.bind(picker._begin_event, function(e){
				
				// 初始化transition
				picker._setTransitionTime(ul, 0);
				clearTimeout(timeout);
				
				var beginTime = picker._getTimeStamp(e);
				var beginY = picker._getY(e);
				
				var translateY = picker._getTranslateY(ul);
				
				// 最大和最小的合法元素
				var min = $("li", ul).index($("li.nu-picker-valid", ul).eq(0));
				var max = $("li", ul).index($("li.nu-picker-valid", ul).eq(-1));
				
				// 移动的时候跟着动
				picker._dialog.bind(picker._move_event, function(event){
					var offsetY = picker._getY(event) - beginY;
					var index = picker._getIndex(translateY + offsetY);
					index = picker._constrain(index, min, max);
					picker._scrollToIndex(ulIndex, index, 0, false);
					return false;
				})
				
				// 结束移动的时候修正,或者触发滚动条件
				picker._dialog.bind(picker._end_event, function(e){
					var timeOffset = picker._getTimeStamp(e) - beginTime;
					var offsetY = picker._getY(e) - beginY;

					// 成功触发条件,开始滚动
					if(timeOffset < 300 && Math.abs(offsetY) > 60){
						rate = 400 / timeOffset;
						var index = picker._getFixedIndex(translateY + offsetY * rate);
						index = picker._constrain(index, min, max);
						timeout = picker._scrollToIndex(ulIndex, index, picker._config.scrollTime, true);
						
					// 修正
					}else{
						var index = picker._getFixedIndex(picker._getTranslateY(ul));
						index = picker._constrain(index, min, max);
						timeout = picker._scrollToIndex(ulIndex, index, picker._config.fixTime, true);
					}
					
					picker._dialog.unbind(picker._move_event);
					picker._dialog.unbind(picker._end_event);
					return false;
				});
				
				return false;
			});
			
			return ul;
		},
		
		_getY:function(e){
			var e = e.originalEvent || e;
			return ("changedTouches" in e) ? e.changedTouches[0].pageY : e.pageY;
		},
		
		_getTimeStamp:function(e){
			var e = e.originalEvent || e;
			return e.timeStamp;
		},
		
		_getTranslateY:function(ul){
			if(ul[0].style[this._prefix + "Transform"]){
				// translateY(0px)
				var transform = ul[0].style[this._prefix + "Transform"];
				var index = transform.indexOf("px)");
				return parseInt(transform.substring(11, index));
			}
			return 0;
		},
		
		_setTranslateY:function(ul, y){
			ul[0].style[this._prefix + "Transform"] = "translateY(" + y + "px)";
		},
		
		_setTransitionTime:function(ul, second){
			// all 0.1s ease-out
			var transition = "all " + second + "s ease-out";
			ul[0].style[this._prefix + "Transition"] = transition;
		},
		
		// 根据坐标计算出最近的需要置于中间的元素
		_getIndex:function(translateY){
			return - (translateY / this._itemHeight - this._config.scrollOffset);
		},
		
		_getFixedIndex:function(translateY){
			return - (Math.round(translateY / this._itemHeight) - this._config.scrollOffset);
		},
		
		
		
		_constrain:function(val, min, max){
			val = Math.max(val, min);
			val = Math.min(val, max);
			return val;
		},
		
		_onItemSelect:function(ul, ulIndex){
			if(this._config.onItemSelect){
				this._config.onItemSelect(ul, ulIndex);
			}
		},
		
		// 把第index个元素置于中间,以0开头
		_scrollToIndex:function(ulIndex, index, time, setValue){
			var ul = this._uls[ulIndex];
			
			var timeout = null;
			
			if(!time){
				this._setTranslateY(ul, - (index - this._config.scrollOffset) * this._itemHeight);
			}else{
				this._setTransitionTime(ul, time / 1000);
				this._setTranslateY(ul, - (index - this._config.scrollOffset) * this._itemHeight);
				var dp = this;
				timeout = setTimeout(function(){
					dp._setTransitionTime(ul, 0);
				}, time);
			}
			
			// 把目标元素置为选中状态
			if(setValue){
				ul.children().eq(index).addClass("nu-picker-select").siblings().removeClass("nu-picker-select");
				this._onItemSelect(ul, ulIndex);
			}
			
			return timeout;
		},
		
		show:function(params){
			this._dialog.show();
			this._itemHeight = this._dialog.find("li:first").outerHeight(true);
			
			// scroll to target
			for(var i = 0; i < this._uls.length; i++){
				var index = this._uls[i].find("li.nu-picker-select").index();
				this.scrollToIndex(i, index, false);
			}
			
			if(this._config.onShow){
				this._config.onShow(params);
			}
		},
		
		hide:function(result){
			this._dialog.hide();
			if(this._config.onHide){
				this._config.onHide(result);
			}
		},
		
		updateData:function(ulIndex, data){
			this._buildLis(this._uls[ulIndex], data);
			this.scrollToIndex(ulIndex, 0, true);
		},
		
		getOutput:function(ulIndex){
			if(ulIndex === undefined){
				var result = [];
				for(var i = 0; i < this._uls.length; i++){
					result.push(this._uls[i].find("li.nu-picker-select").attr("value"));
				}
				return result;
			}else{
				return this._uls[ulIndex].find("li.nu-picker-select").attr("value");
			}
		},
		
		getUl:function(ulIndex){
			return this._uls[ulIndex];
		},
		
		scrollToIndex:function(ulIndex, index, animate){
			var time;
			if(animate){
				time = this._config.scrollTime;
			}else{
				time = 0;
			}
			this._scrollToIndex(ulIndex, index, time, true);
		},
		
		scrollToValue:function(ulIndex, value, animate){
			var ul = this._uls[ulIndex];
			var index = ul.find("li[value=" + value + "]").index();
			
			this.scrollToIndex(ulIndex, index, animate);
		},
		
		scrollToIndexs:function(indexs, animate){
			for(var i = 0; i < this._config.scrollers.length; i++){
				this.scrollToIndex(i, indexs[i], animate, true);
			}
		},
		
		scrollToValues:function(values, animate){
			for(var i = 0; i < this._config.scrollers.length; i++){
				this.scrollToValue(i, values[i], animate, true);
			}
		}
	};
});
